﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace Jemgine.Engine.Renderer
{
    public class VertexPusher
    {
        private GraphicsDevice GraphicsDevice;
		internal VertexPositionTexture[] VertexBuffer = new VertexPositionTexture[4];
		Vector2[] TempVectors = new Vector2[4];

        public RenderEffect Effect { get; set; }

        public VertexPusher(GraphicsDevice GraphicsDevice)
        {
            reset(GraphicsDevice);
        }

        public void reset(GraphicsDevice GraphicsDevice)
        {
            this.GraphicsDevice = GraphicsDevice;
        }
		
        public void DrawFullScreenQuad(Vector2 TextureScale, Camera Cam)
        {
            VertexBuffer[0].Position = new Vector3(Cam.UnProject(new Vector2(0, 0)), 0);
            VertexBuffer[1].Position = new Vector3(Cam.UnProject(new Vector2(Cam.viewportDimensions.X, 0)), 0);
            VertexBuffer[3].Position = new Vector3(Cam.UnProject(new Vector2(Cam.viewportDimensions.X, Cam.viewportDimensions.Y)), 0);
            VertexBuffer[2].Position = new Vector3(Cam.UnProject(new Vector2(0, Cam.viewportDimensions.Y)), 0);

            VertexBuffer[0].TextureCoordinate = new Vector2(VertexBuffer[0].Position.X, VertexBuffer[0].Position.Y) * TextureScale;
            VertexBuffer[1].TextureCoordinate = new Vector2(VertexBuffer[1].Position.X, VertexBuffer[1].Position.Y) * TextureScale;
            VertexBuffer[2].TextureCoordinate = new Vector2(VertexBuffer[2].Position.X, VertexBuffer[2].Position.Y) * TextureScale;
            VertexBuffer[3].TextureCoordinate = new Vector2(VertexBuffer[3].Position.X, VertexBuffer[3].Position.Y) * TextureScale;

            DrawTriangleStrip(VertexBuffer);
        }

        public void RawFullScreenQuad()
        {
            VertexBuffer[0].Position = new Vector3(-1, -1, 0);
            VertexBuffer[1].Position = new Vector3(-1, 1, 0);
            VertexBuffer[3].Position = new Vector3(1, 1, 0);
            VertexBuffer[2].Position = new Vector3(1, -1, 0);

            VertexBuffer[0].TextureCoordinate = new Vector2(0, 1);
            VertexBuffer[1].TextureCoordinate = new Vector2(0, 0);
            VertexBuffer[3].TextureCoordinate = new Vector2(1, 0);
            VertexBuffer[2].TextureCoordinate = new Vector2(1, 1);

            DrawTriangleStrip(VertexBuffer);
        }

        public void DrawOrientedSprite(
            Vector2 Orientation,
            bool Flip)
        {

            VertexBuffer[2].Position = new Vector3(Orientation.X - Orientation.Y, Orientation.X + Orientation.Y, 0.0f);
            VertexBuffer[3].Position = new Vector3(-(Orientation.X + Orientation.Y), Orientation.X - Orientation.Y, 0.0f);
            VertexBuffer[1].Position = new Vector3(Orientation.Y - Orientation.X, -(Orientation.X + Orientation.Y), 0.0f);
            VertexBuffer[0].Position = new Vector3(Orientation.X + Orientation.Y, Orientation.Y - Orientation.X, 0.0f);
            
            if (!Flip)
			{
				VertexBuffer[0].TextureCoordinate = new Vector2(0, 1);
				VertexBuffer[1].TextureCoordinate = new Vector2(0, 0);
				VertexBuffer[3].TextureCoordinate = new Vector2(1, 0);
				VertexBuffer[2].TextureCoordinate = new Vector2(1, 1);
			}
			else
			{
				VertexBuffer[0].TextureCoordinate = new Vector2(1, 1);
				VertexBuffer[1].TextureCoordinate = new Vector2(1, 0);
				VertexBuffer[3].TextureCoordinate = new Vector2(0, 0);
				VertexBuffer[2].TextureCoordinate = new Vector2(0, 1);
			}

            DrawTriangleStrip(VertexBuffer);
        }

		public void DrawSprite(bool Flip)
		{
			VertexBuffer[0].Position = new Vector3(-0.5f, -0.5f, 0);
			VertexBuffer[1].Position = new Vector3(-0.5f, 0.5f, 0);
			VertexBuffer[3].Position = new Vector3(0.5f, 0.5f, 0);
			VertexBuffer[2].Position = new Vector3(0.5f, -0.5f, 0);

			if (!Flip)
			{
				VertexBuffer[0].TextureCoordinate = new Vector2(0, 1);
				VertexBuffer[1].TextureCoordinate = new Vector2(0, 0);
				VertexBuffer[3].TextureCoordinate = new Vector2(1, 0);
				VertexBuffer[2].TextureCoordinate = new Vector2(1, 1);
			}
			else
			{
				VertexBuffer[0].TextureCoordinate = new Vector2(1, 1);
				VertexBuffer[1].TextureCoordinate = new Vector2(1, 0);
				VertexBuffer[3].TextureCoordinate = new Vector2(0, 0);
				VertexBuffer[2].TextureCoordinate = new Vector2(0, 1);
			}

            DrawTriangleStrip(VertexBuffer);
        }

        public void DrawAxisAlignedQuad(Vector2 Min, Vector2 Max)
        {
            VertexBuffer[0].Position = new Vector3(Min.X, Min.Y, 0);
            VertexBuffer[1].Position = new Vector3(Min.X, Max.Y, 0);
            VertexBuffer[3].Position = new Vector3(Max.X, Max.Y, 0);
            VertexBuffer[2].Position = new Vector3(Max.X, Min.Y, 0);

            
                VertexBuffer[0].TextureCoordinate = new Vector2(0, 1);
                VertexBuffer[1].TextureCoordinate = new Vector2(0, 0);
                VertexBuffer[2].TextureCoordinate = new Vector2(1, 1);
                VertexBuffer[3].TextureCoordinate = new Vector2(1, 0);
            
            DrawTriangleStrip(VertexBuffer);
        }

        public void SetShadowTextureCoords()
        {
            VertexBuffer[0].TextureCoordinate = new Vector2(0, 0);
            VertexBuffer[1].TextureCoordinate = new Vector2(1, 0);
            VertexBuffer[2].TextureCoordinate = new Vector2(0, 10);
            VertexBuffer[3].TextureCoordinate = new Vector2(1, 10);
        }

		public void DrawSpriteOutline(float Width)
		{
			TempVectors[0] = new Vector2(-0.5f, -0.5f);
			TempVectors[1] = new Vector2(-0.5f, 0.5f);
			TempVectors[2] = new Vector2(0.5f, 0.5f);
			TempVectors[3] = new Vector2(0.5f, -0.5f);

			DrawLine(TempVectors[0], TempVectors[1], Width);
			DrawLine(TempVectors[1], TempVectors[2], Width);
			DrawLine(TempVectors[2], TempVectors[3], Width);
			DrawLine(TempVectors[3], TempVectors[0], Width);
		}

        public void DrawLine(Vector2 Start, Vector2 End, float Width)
        {
            Vector2 LineNormal = Jemgine.Math.Vector.EdgeNormal(Start, End);
            LineNormal *= Width * 0.5f;

            VertexBuffer[0].Position = new Vector3(Start + LineNormal, 0);
            VertexBuffer[1].Position = new Vector3(Start - LineNormal, 0);
            VertexBuffer[3].Position = new Vector3(End - LineNormal, 0);
            VertexBuffer[2].Position = new Vector3(End + LineNormal, 0);
            VertexBuffer[0].TextureCoordinate = new Vector2(0, 1);
            VertexBuffer[1].TextureCoordinate = new Vector2(0, 0);
            VertexBuffer[3].TextureCoordinate = new Vector2(1, 0);
            VertexBuffer[2].TextureCoordinate = new Vector2(1, 1);

            DrawTriangleStrip(VertexBuffer);
        }

        public void DrawTriangleStrip(VertexPositionTexture[] Verticies)
        {
            Effect.Apply();
            GraphicsDevice.DrawUserPrimitives<VertexPositionTexture>
                (PrimitiveType.TriangleStrip, Verticies, 0, Verticies.Length - 2);
        }

        public void DrawTriangles(VertexPositionTexture[] Verticies)
        {
            Effect.Apply();
            GraphicsDevice.DrawUserPrimitives<VertexPositionTexture>
                (PrimitiveType.TriangleList, Verticies, 0, Verticies.Length / 3);
        }
    }
}
